package cz.data.common.mongo.manage;

import com.alibaba.fastjson.JSONObject;
import cz.data.common.support.FormatConstant;
import cz.data.common.support.db.core.DbColumn;
import cz.data.common.support.db.core.DbTable;
import cz.data.common.support.db.manage.ManageDialect;
import cz.data.common.support.metadata.JavaTypeEnum;
import cz.data.common.utils.ThrowableUtil;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

public class MongoManageDialect implements ManageDialect {

    @Override
    public void preProcessData(DbTable table, JSONObject record) {
        List<DbColumn> columns = table.getColumns();
        List<String> keys = new ArrayList<>(record.keySet());
        for (String key : keys) {
            boolean filter = true;
            for (DbColumn column : columns) {
                Object value = record.get(column.getColName());
                if (Objects.isNull(value))
                    continue;
                if (StringUtils.equals(column.getColName(), key)) {
                    filter = false;
                    JavaTypeEnum typeEnum = JavaTypeEnum.match(column.getDataType());
                    if (typeEnum == JavaTypeEnum.DATE) {
                        if (value instanceof String) {
                            String strValue = value.toString();
                            Date date = ThrowableUtil.callable(
                                    () ->DateUtils.parseDate(strValue, FormatConstant.DATE_FORMATS), false
                            );
                            record.put(key, date);
                        } else if (value instanceof Long) {
                            Long longValue = (Long) value;
                            record.put(key, new Date(longValue));
                        }
                    } else if (typeEnum == JavaTypeEnum.INT) {
                        String strValue = value.toString();
                        int intValue = NumberUtils.toInt(strValue, 0);
                        record.put(key, intValue);
                    } else if (typeEnum == JavaTypeEnum.DOUBLE) {
                        String strValue = value.toString();
                        double doubleValue = NumberUtils.toDouble(strValue, 0d);
                        record.put(key, doubleValue);
                    } else if (typeEnum == JavaTypeEnum.FLOAT) {
                        String strValue = value.toString();
                        float floatValue = NumberUtils.toFloat(strValue);
                        record.put(key, floatValue);
                    } else if (typeEnum == JavaTypeEnum.LONG) {
                        String strValue = value.toString();
                        long longValue = NumberUtils.toLong(strValue, 0L);
                        record.put(key, longValue);
                    } else if (typeEnum == JavaTypeEnum.BYTE) {
                        String strValue = value.toString();
                        byte byteValue = NumberUtils.toByte(strValue);
                        record.put(key, byteValue);
                    } else if (typeEnum == JavaTypeEnum.SHORT) {
                        String strValue = value.toString();
                        short shortValue = NumberUtils.toShort(strValue);
                        record.put(key, shortValue);
                    } else if (typeEnum == JavaTypeEnum.BOOLEAN) {
                        String strValue = value.toString();
                        boolean booleanValue = BooleanUtils.toBoolean(strValue);
                        record.put(key, booleanValue);
                    } else if (typeEnum == JavaTypeEnum.OBJECT) {
                        JSONObject object = (JSONObject) ThrowableUtil.callable(
                                () -> JSONObject.toJSON(value), false
                        );
                        record.put(key, object);
                    }
                }
            }
            if (filter) {
                record.remove(key);
            }
        }
    }
}
